// sqlite包提供了对SQLite数据库的访问抽象层
// 设计目标是提供一个干净的接口, 与具体的SQLite驱动实现解耦
// 这种设计便于在测试中使用模拟（Mock）对象替代真实数据库
package sqlite

import (
	"context"
	"errors"
	"fmt"
	"time"

	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

// DB GORM数据库接口
// 定义了数据库操作的抽象方法
type DB interface {
	// AutoMigrate 自动迁移模型到数据库
	AutoMigrate(dst ...any) error
	// Create 创建一条记录
	Create(value any) error
	// Save 保存一条记录（创建或更新）
	Save(value any) error
	// First 查询第一条匹配的记录
	First(dest any, conds ...any) error
	// Find 查询多条记录
	Find(dest any, conds ...any) error
	// Where 条件查询
	Where(query any, args ...any) DB
	// Preload 预加载关联
	Preload(column string, conditions ...any) DB
	// Transaction 执行事务
	Transaction(fc func(tx DB) error) error
}

// Options SQLite连接选项
type Options struct {
	Path              string          // 数据库文件路径
	MaxOpenConns      int             // 最大打开连接数
	MaxIdleConns      int             // 最大空闲连接数
	ConnMaxLifetime   time.Duration   // 连接最大存活时间
	LogLevel          logger.LogLevel // 日志级别
	AutoMigrateModels []any           // 自动迁移的模型
}

// gormDB GORM数据库实现
// 包装了原生的gorm.DB
type gormDB struct {
	db *gorm.DB // 原生GORM客户端
}

// NewClient 创建新的SQLite客户端
// 参数:
// - ctx: 上下文, 用于控制连接超时
// - options: SQLite连接选项
// 返回:
// - DB: 数据库接口
// - error: 错误信息
func NewClient(ctx context.Context, options Options) (DB, error) {
	// 设置GORM配置
	gormConfig := &gorm.Config{
		Logger: logger.Default.LogMode(options.LogLevel),
	}

	// 创建SQLite数据库连接
	db, err := gorm.Open(sqlite.Open(options.Path), gormConfig)
	if err != nil {
		return nil, fmt.Errorf("连接SQLite失败: %w", err)
	}

	// 获取原生SQL数据库连接并配置
	sqlDB, err := db.DB()
	if err != nil {
		return nil, fmt.Errorf("获取SQL数据库失败: %w", err)
	}

	// 设置连接池参数
	if options.MaxOpenConns > 0 {
		sqlDB.SetMaxOpenConns(options.MaxOpenConns)
	}
	if options.MaxIdleConns > 0 {
		sqlDB.SetMaxIdleConns(options.MaxIdleConns)
	}
	if options.ConnMaxLifetime > 0 {
		sqlDB.SetConnMaxLifetime(options.ConnMaxLifetime)
	}

	// 自动迁移模型
	if len(options.AutoMigrateModels) > 0 {
		if err := db.AutoMigrate(options.AutoMigrateModels...); err != nil {
			return nil, fmt.Errorf("自动迁移模型失败: %w", err)
		}
	}

	return &gormDB{db: db}, nil
}

// AutoMigrate 自动迁移模型到数据库
func (g *gormDB) AutoMigrate(dst ...any) error {
	return g.db.AutoMigrate(dst...)
}

// Create 创建一条记录
// 参数:
// - value: 要创建的记录
// 返回:
// - error: 错误信息
func (g *gormDB) Create(value any) error {
	result := g.db.Create(value)
	return result.Error
}

// Save 保存一条记录（创建或更新）
// 参数:
// - value: 要保存的记录
// 返回:
// - error: 错误信息
func (g *gormDB) Save(value any) error {
	result := g.db.Save(value)
	return result.Error
}

// First 查询第一条匹配的记录
// 参数:
// - dest: 接收查询结果的变量
// - conds: 查询条件
// 返回:
// - error: 错误信息
func (g *gormDB) First(dest any, conds ...any) error {
	result := g.db.First(dest, conds...)
	return result.Error
}

// Find 查询多条记录
// 参数:
// - dest: 接收查询结果的变量
// - conds: 查询条件
// 返回:
// - error: 错误信息
func (g *gormDB) Find(dest any, conds ...any) error {
	result := g.db.Find(dest, conds...)
	return result.Error
}

// Where 条件查询
// 参数:
// - query: 查询条件
// - args: 查询参数
// 返回:
// - DB: 数据库接口
func (g *gormDB) Where(query any, args ...any) DB {
	return &gormDB{db: g.db.Where(query, args...)}
}

// Preload 预加载关联
// 参数:
// - column: 关联的列名
// - conditions: 预加载条件
// 返回:
// - DB: 数据库接口
func (g *gormDB) Preload(column string, conditions ...any) DB {
	return &gormDB{db: g.db.Preload(column, conditions...)}
}

// Transaction 执行事务
// 参数:
// - fc: 事务函数
// 返回:
// - error: 错误信息
func (g *gormDB) Transaction(fc func(tx DB) error) error {
	return g.db.Transaction(func(tx *gorm.DB) error {
		return fc(&gormDB{db: tx})
	})
}

// IsRecordNotFoundError 判断是否为记录未找到错误
// 参数:
// - err: 错误信息
// 返回:
// - bool: 是否为记录未找到错误
func IsRecordNotFoundError(err error) bool {
	return errors.Is(err, gorm.ErrRecordNotFound)
}
